﻿using Intex.Controls.EventHandlers;
using Intex.Controls.Helpers;
using Intex.Controls.Stopwatch.Controllers;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace Intex.Controls.Stopwatch
{
    /// <summary>
    /// StopwatchControl.xaml 的交互逻辑
    /// </summary>
    public partial class StopwatchControl : UserControl
    {
        #region ==CQTY===========
        public static readonly DependencyProperty CQTYProperty = DependencyProperty.Register("CQTY",
            typeof(double), typeof(StopwatchControl),
            new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
        public double CQTY
        {
            get
            {
                return (double)GetValue(CQTYProperty);
            }
            set
            {
                SetValue(CQTYProperty, value);
            }
        }

        #endregion

        #region ==CLength===========
        public static readonly DependencyProperty CLengthProperty = DependencyProperty.Register("CLength",
            typeof(double), typeof(StopwatchControl),
            new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnCLengthChanged));
        public double CLength
        {
            get
            {
                return (double)GetValue(CLengthProperty);
            }
            private set
            {
                SetValue(CLengthProperty, value);
            }
        }

        private static void OnCLengthChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var src = sender as StopwatchControl;
            if (src != null)
            {
                src.CLength = (double)e.NewValue;
                src.CQTY = src.CLength * 1000;
            }
        }
        #endregion

        private SerialPort _SerialPort = new SerialPort();

        private Thread thBackgroundWoker = null;

        public StopwatchControl()
        {
            if (DesignerProperties.GetIsInDesignMode(this))
                return;

            InitializeComponent();
        }

        private bool isContinue = true;
        private void ReadWork()
        {
            while (isContinue)
            {
                try
                {
                    this.OpenCom();
                    this.Controller.SendCommand(this._SerialPort);
                    Thread.Sleep(10);
                    var obj = this.Controller.ReadData(this._SerialPort);
                    this.Dispatcher.Invoke(new Action<StopwatchValue>(RefreshData), DispatcherPriority.Send, obj);

                    if (this._SerialPort.IsOpen)
                    {
                        this._SerialPort.DiscardInBuffer();
                        this._SerialPort.DiscardOutBuffer();
                    }
                    this.CloseCom();

                    Thread.Sleep(500);
                }
                catch (Exception ex)
                {
                    if (!(ex is ThreadAbortException))
                    {
                        isContinue = false;
                        MessageBox.Show(ex.Message, "出错了", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                }
            }
        }

        private void RefreshData(StopwatchValue value)
        {
            this.CLength = (double)value.Length;
            this.Unit = value.Unit;
        }
        bool IsRun = false;
        public void Start()
        { 
            if (IsRun)
                return;
            if (thBackgroundWoker != null && thBackgroundWoker.IsAlive)
            {
                thBackgroundWoker.Abort();
            }

            RestoreConfig();

            thBackgroundWoker = new Thread(new ThreadStart(ReadWork));
            thBackgroundWoker.IsBackground = true;
            isContinue = true;
            thBackgroundWoker.Start();
            IsRun = true;
        }

        public void Stop()
        {
            if (thBackgroundWoker != null && thBackgroundWoker.IsAlive)
            {
                thBackgroundWoker.Abort();
            }

            thBackgroundWoker = null;
        }

        private IStopwatchController _Controller = null;
        public IStopwatchController Controller
        {
            get
            {
                if (_Controller == null)
                    _Controller = StopwatchControllerFactory.CreateContoller(this.StopwatchType);
                return _Controller;
            }
        }

        public StopwatchType StopwatchType
        { get; private set; }

        public void OpenCom()
        {
            if (_SerialPort.IsOpen)
            {
                _SerialPort.Close();
            }
            try
            {
                _SerialPort.Open();
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("打开串口出错！{0}详细原因：", Environment.NewLine) + ex.Message);
            }
        }

        public void CloseCom()
        {
            if (this._SerialPort.IsOpen)
            {
                this._SerialPort.Close();
            }
        }


        public static readonly DependencyProperty UnitProperty = DependencyProperty.Register("Unit", typeof(string), typeof(StopwatchControl),
            new FrameworkPropertyMetadata() { DefaultValue = "米" });

        /// <summary>
        /// 码表显示单位
        /// </summary>
        public string Unit
        {
            get { return (string)GetValue(UnitProperty); }
            set { SetValue(UnitProperty, value); }
        }

        public static readonly DependencyProperty ConfigFileProperty = DependencyProperty.Register("ConfigFile", typeof(string), typeof(StopwatchControl),
            new FrameworkPropertyMetadata() { DefaultValue = "Stopwatch" });

        public string ConfigFile
        {
            get { return (string)GetValue(ConfigFileProperty); }
            set { SetValue(ConfigFileProperty, value); }
        }

        private void Label_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (StopwatchControlConfigDialog.ShowConfig(this) == true)
            {
                this.Stop();
                this.Start();
            }
        }

        public void RestoreConfig()
        {
            var config = LoadConfig();

            if (!string.IsNullOrWhiteSpace(config.PortName))
                this._SerialPort.PortName = config.PortName;
            this._SerialPort.BaudRate = config.BaudRate;
            this._SerialPort.DataBits = config.DataBits;
            this._SerialPort.Parity = config.Parity;
            this._SerialPort.StopBits = config.StopBits;
            this._SerialPort.Handshake = config.Handshake;

            this.StopwatchType = config.StopwatchType;

            this._Controller = null;
        }

        internal string ConfigFileName
        {
            get
            {
                var path = System.IO.Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "StopwatchConfig");
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }

                return System.IO.Path.Combine(path, ConfigFile.Trim() + ".xml");
            }
        }

        internal StopwatchConfig LoadConfig()
        {
            StopwatchConfig config = null;
            if (File.Exists(ConfigFileName))
            {
                var xml = File.ReadAllText(ConfigFileName, Encoding.UTF8);
                config = XmlSerializerHelper.Deserialize<StopwatchConfig>(xml);
            }

            if (config == null)
                config = new StopwatchConfig();

            return config;
        }
    }
}
